package com.webrtc.config.websocket;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author liuzhiqiang
 */
@ServerEndpoint(value = "/")
@Component
@Slf4j
public class WebSocketServerEndpoint {

    /**
     * 当前客户端会话绑定得对象
     */
    private ConnectUser connectUser;

    /**
     * 当前客户端会话
     */
    private Session session;

    /**
     * 连接建立成功调用的方法
     *
     * @param session 可选的参数。session为与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
    }


    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        log.info("客户端[{}],关闭连接", connectUser);
        log.info("当前登录人数[{}]", WebSocketResources.getUserWebSocketMap().size());
        if (connectUser != null) {
            WebSocketResources.remove(connectUser.getUserId());
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message) {
        log.info("收到客户端消息【{}】", message);
        MessageBody messageBody = JSONObject.parseObject(message, MessageBody.class);
        if (messageBody.getInstruct() != null) {
            if (messageBody.getInstruct().equals(1)) {
                // 建立连接
                ConnectUser connectUser = new ConnectUser();
                connectUser.setUserId(UUID.randomUUID().toString());
                connectUser.setUsername(messageBody.getData().getString("username"));
                connectUser.setRole(messageBody.getData().getInteger("role"));
                this.connectUser = connectUser;
                WebSocketResources.addWebSocket(connectUser.getUserId(), this);

                JSONObject data = new JSONObject();
                data.put("instruct", messageBody.getInstruct());
                // 获取频道中其余的用户
                List<ConnectUser> list = new ArrayList<>();
                WebSocketResources.getUserWebSocketMap().forEach((userId, webSocketServerEndpoint) -> {
                    if (!StringUtils.equals(userId, connectUser.getUserId())) {
                        list.add(webSocketServerEndpoint.connectUser);
                    }
                });
                JSONObject data2 = new JSONObject();
                data2.put("currentUser", connectUser);
                data2.put("attachableUser", list);

                data.put("data", data2);
                this.sendMessage(data.toJSONString());

                log.info("当前登录人数[{}]", WebSocketResources.getUserWebSocketMap().size());
            } else if (messageBody.getInstruct().equals(2)) {
                // 信令
                // 将信息推发给客户端
                // 接收者
                String recipient = messageBody.getData().getString("recipient");
                if (StringUtils.isNotEmpty(recipient)) {
                    // 构建消息
                    messageBody.getData().put("sender", connectUser);
                    // 消息是否发送给全体客户端
                    if (StringUtils.equals(recipient, "ALL")) {
                        WebSocketResources.getUserWebSocketMap().forEach((userId, webSocketServerEndpoint) -> {
                            // 接收者不能是自己
                            if (!StringUtils.equals(connectUser.getUserId(), userId)) {
                                webSocketServerEndpoint.sendMessage(JSONObject.toJSONString(messageBody));
                            }
                        });
                    } else {
                        if (!StringUtils.equals(connectUser.getUserId(), recipient)) {
                            WebSocketServerEndpoint webSocketServerEndpoint = WebSocketResources.getWebSocketServerEndpoint(recipient);
                            if (webSocketServerEndpoint != null) {
                                webSocketServerEndpoint.sendMessage(JSONObject.toJSONString(messageBody));
                            }
                        }
                    }
                }

            } else if (messageBody.getInstruct().equals(3)) {
                this.onClose();
            }

        }

    }

    /**
     * 发生错误时调用
     *
     * @param error
     */
    @OnError
    public void onError(Throwable error) {
        log.error("发生错误[{}]", error);
        log.info("当前登录人数[{}]", WebSocketResources.getUserWebSocketMap().size());
    }


    public void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            log.info("给客户端发送消息时出错【{}】", message);
            log.error("给客户端发送消息时出错", e);
        }
    }
}
